use async_trait::async_trait;
use rpc::{RpcChannel, RpcResult};
use rpc::bootstrap::BootstrapBuilder;
use rpc_derive::{router, rpc_service};
use rpc_server::server::RpcServerBuilder;

#[derive(Debug, Clone)]
pub struct MessageObject {
    pub content: String,
}

pub struct OkResp {

}

#[rpc_service]
#[async_trait]
pub trait SendMessageService {

    #[path="send"]
    async fn send(&mut self, channel: &mut impl RpcChannel, data: i32) -> RpcResult<i32>;

    #[path="handle"]
    async fn handle(&mut self, channel: &mut impl RpcChannel, data: String) -> RpcResult<()>;
}

// pub struct SendMessageServiceImpl {
//     context: Box<dyn rpc::RpcContext>,
// }
// impl SendMessageServiceImpl {
//     pub fn new(context: Box<dyn rpc::RpcContext>) -> SendMessageServiceImpl {
//         SendMessageServiceImpl {
//             context,
//         }
//     }
// }
//
// #[async_trait]
// impl SendMessageService for SendMessageServiceImpl {
//
//     async fn send(&mut self, channel: &mut impl RpcChannel, data: i32) -> RpcResult<i32> {
//         let bytes = rpc::encode(&*self.context, data)?;
//         let local_seq = self.context.get_local_seq_creator().create_seq();
//         let header = rpc::dto::RpcHeader::new("send", local_seq.clone(), 0);
//         let rpc_data_bytes = rpc::dto::RpcDataBytes::new(header, bytes);
//         let result = rpc::encode_header(&*self.context, rpc_data_bytes)?;
//         let data = channel.write(rpc::dto::RpcHeader::new("send", local_seq, 0), result).await?;
//         let value = rpc::decode(&*self.context, data)?;
//         Ok(value)
//     }
//
//     async fn handle(&mut self, channel: &mut impl RpcChannel, data: String) -> RpcResult<()> {
//         let bytes = rpc::encode(&*self.context, data)?;
//         let local_seq = self.context.get_local_seq_creator().create_seq();
//         let header = rpc::dto::RpcHeader::new("handle", local_seq.clone(), 0);
//         let rpc_data_bytes = rpc::dto::RpcDataBytes::new(header, bytes);
//         let result = rpc::encode_header(&*self.context, rpc_data_bytes)?;
//         let data = channel.write(RpcHeader::new("handle", local_seq, 0), result).await?;
//         let value = rpc::decode(&*self.context, data)?;
//         Ok(value)
//     }
// }


#[macro_export]
macro_rules! server_sender {

    ($ident: ident, $exp: ident) => {
        let router_factory_name = format!("{}RouterFactory", stringify!($exp));
        use proc_macro2::Ident;
        use quote::format_ident;
        let router_factory = format_ident!("{}", router_factory_name);
        router_factory {
            channel: std::sync::Arc::new(Box::new($ident)),
        }
    }
}


// #[tokio::test]
async fn test() -> RpcResult<()> {
    // server_sender!(RpcTestChannel, SendMessageService);
    let bootstrap = BootstrapBuilder::new();
    let server = RpcServerBuilder::new(bootstrap, 8888)
        .build();
    server.start_server().await.unwrap();

    // let message_service = SendMessageServiceImpl::new(Arc::new(Box::new(RpcTestChannel)));
    // let context_clone = context.clone();
    // let mut message_service = sender!(context_clone, SendMessageService);
    //
    // let mut channel = context.build_channel(ChannelId::new(1)).unwrap();
    // let result = message_service.send(&mut channel, 32).await;
    // if let Ok(result) = result {
    //     info!("result:  {:?}", result);
    // } else {
    //     info!("error: {:?}", result);
    // }
    Ok(())
}

